// create database test0;

//创建MySQL表
/*
CREATE TABLE IF NOT EXISTS yonghu(
userid INT(10) UNSIGNED PRIMARY KEY NOT NULL,
username CHAR(255) NOT NULL COMMENT '用户名',
password CHAR(32) NOT NULL COMMENT '密码',
phone CHAR(128) NOT NULL,
mail CHAR(128) NOT NULL,
regist_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
*/

// API 测试
/*
curl -d 'n=1000' http://172.24.16.6:1323/api/v1/usercreate
curl -d 'userid=1000' http://172.24.16.6:1323/api/v1/userinfo
curl -d 'userid=1000' -d 'newname=杭州' http://172.24.16.6:1323/api/v1/usernameupdate
curl -d 'userid=1000' http://172.24.16.6:1323/api/v1/userinfo
*/

package main

import (
  "net/http"
  "github.com/labstack/echo/v4"
  "github.com/labstack/echo/v4/middleware"
  jqr "github.com/jinquan0/jqdb/jqmysql"
  "fmt"
  "io/ioutil"
  "gopkg.in/yaml.v2"
  "flag"
  "log"
  "strconv"
  "encoding/json"
)

type ST_MysqlConfig struct {
    Host  string `yaml:"host"`
    Port  string `yaml:"port"`
    User  string `yaml:"user"`
    Pass  string `yaml:"pass"`
    Sslca  string `yaml:"sslca"`
    Db  string `yaml:"db"`
}

type ST_Config struct {
  Mysql ST_MysqlConfig `yaml:"mysql"`
}

var (
  GlobalConfig *ST_Config
)

func load_config_file(f string) *ST_Config {
  dat,err := ioutil.ReadFile(f)
  if err != nil {
    fmt.Println(err.Error())
    return nil
  }

  var cfg ST_Config
  err = yaml.Unmarshal(dat, &cfg)
  if err != nil {
    fmt.Println(err.Error())
    return nil
  }
  return &cfg
}

type ST_QueryReply struct{
    Userid    int  `json:"userid"`
    Username    string  `json:"username"`
    Password    string  `json:"password"`
    Phone       string  `json:"phone"`
    Mail        string  `json:"mail"`
}
func AnyarrayAlloc_QueryReply(sz int) []interface{} {
    any_array := make([]interface{}, sz, sz)
    for i:=0; i < sz; i++ { 
        any_array[i]=new(ST_QueryReply) 
    }
    return any_array
}
func UserInfo(userid int, cfg ST_MysqlConfig) (bool, string) {
  e := &jqr.ST_MySQL_Endpoint {
    Host:  cfg.Host,
    Port:  cfg.Port,
    User:  cfg.User,
    Pass:  cfg.Pass,
    Sslca: cfg.Sslca,
    Db:    cfg.Db,
  }
  BUFFER := AnyarrayAlloc_QueryReply(16)
  db := jqr.MyConn(e)

  q:=&jqr.ST_MyCommonQuery {
    Sql: "select userid,username,password,phone,mail from yonghu where `userid`=" + strconv.Itoa(userid) +";" ,
    AnyArray: BUFFER,
  }
  _,maps,numrow := jqr.MyCommonSelect2Maps(*q, db)
  jqr.MyDisconn(db)
  
  var retval bool = false
  var mString string = "[{}]"
  if numrow > 0 {
    retval = true
    mjson,_ :=json.Marshal(maps)
    mString =string(mjson)
    log.Printf("print mString:%s",mString)
  }
  return retval, mString

}


func UserInsert(u ST_QueryReply, cfg ST_MysqlConfig) {
  e := &jqr.ST_MySQL_Endpoint {
    Host:  cfg.Host,
    Port:  cfg.Port,
    User:  cfg.User,
    Pass:  cfg.Pass,
    Sslca: cfg.Sslca,
    Db:    cfg.Db,
  }

  db := jqr.MyConn(e)

  jqr.MyInsert( db, 
      "INSERT IGNORE INTO yonghu(`userid`, `username`, `password`, `phone`, `mail`) VALUES (?,?,?,?,?)", u ) 

  jqr.MyDisconn(db)

}


type ST_UsernameUpdate struct{
    Username    string  `json:"username"`
    Userid    int  `json:"userid"`
}
func UsernameUpdate(id int, newname string, cfg ST_MysqlConfig) {
  e := &jqr.ST_MySQL_Endpoint {
    Host:  cfg.Host,
    Port:  cfg.Port,
    User:  cfg.User,
    Pass:  cfg.Pass,
    Sslca: cfg.Sslca,
    Db:    cfg.Db,
  }

  d:=&ST_UsernameUpdate{
    Userid: id,
    Username: newname,
  }

  db := jqr.MyConn(e)

  jqr.MyUpdate( db, 
      "UPDATE yonghu SET `username`=? WHERE `userid`=?", *d ) 

  jqr.MyDisconn(db)

}

func UserGenerator(userid int) ST_QueryReply {
  u := ST_QueryReply {
    Userid: userid,
    Username: CnNameGenerator(),
    Password: PassGenerator(8),
    Phone: PhoneGenerator(),
    Mail: MailGenerator(),
  }
  // log.Println(u)
  return u
}

//--------------------------- Handler --------------------------------
func handler_healthy(c echo.Context) error {
    return c.String(http.StatusOK, "ok")
}

func handler_userinfo(c echo.Context) error {
  userid:= c.FormValue("userid")
  i_userid,_:=strconv.Atoi(userid)  
  ok,info := UserInfo(i_userid, GlobalConfig.Mysql)
  var StatusCode int = 403
  if ok == true {
    StatusCode = 200
    return c.String(StatusCode, info)
  }
  return c.String(StatusCode, "error")
}

func handler_usercreate(c echo.Context) error {
  n := c.FormValue("n")
  N,_:=strconv.Atoi(n)
  for i:=1 ; i <= N; i++ {
    UserInsert(UserGenerator(i), GlobalConfig.Mysql)
  }
  return c.String(200, "ok")
}

func handler_usernameupdate(c echo.Context) error {
  userid:= c.FormValue("userid")
  newname:=c.FormValue("newname")
  i_userid,_:=strconv.Atoi(userid)  
  UsernameUpdate(i_userid, newname, GlobalConfig.Mysql)
  return c.String(200, "ok")
}

var (
  // flagconf is the config flag.
  flagconf string
)

func init() {
  flag.StringVar(&flagconf, "conf", "config.yaml", "config path, eg: -conf config.yaml")
}


func main() {
  
  flag.Parse()

  GlobalConfig = load_config_file(flagconf)

  e := echo.New()
  // Middleware
  e.Use(middleware.Logger())
  e.Use(middleware.Recover())

  // add routes
  e.GET("/api/v1/healthy", handler_healthy)
  e.POST("/api/v1/userinfo", handler_userinfo)
  e.POST("/api/v1/usercreate", handler_usercreate)
  e.POST("/api/v1/usernameupdate", handler_usernameupdate)
  // Start server
  e.Logger.Fatal(e.Start(":1323"))
}